package com.wsjzzcbq.wsjzcode.execute;

import com.wsjzzcbq.wsjzcode.bean.Code;
import com.wsjzzcbq.wsjzcode.bean.ExecuteResult;
import com.wsjzzcbq.wsjzcode.bean.JavaCode;
import com.wsjzzcbq.wsjzcode.code.CodeRunResultMap;
import com.wsjzzcbq.wsjzcode.compile.JavaCodeCompiler;
import com.wsjzzcbq.wsjzcode.consts.MsgConsts;
import com.wsjzzcbq.wsjzcode.util.JavaCodeUitls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

/**
 * JavaExecuter
 *
 * @author wsjz
 * @date 2023/07/06
 */
@Component
public class JavaExecuter implements Executer{

    @Qualifier("javaCodeMemoryCompiler")
    @Autowired
    private JavaCodeCompiler javaCodeCompiler;

    @Override
    public void exec(Code code) {
        JavaCode javaCode = (JavaCode)code;
        ExecuteResult result = new ExecuteResult();
        result.setCode(javaCode);

        Map<String, Object> compileResult =  javaCodeCompiler.compile(javaCode.getCode());

        if (!(Boolean) compileResult.get("result")) {
            result.setResult(ExecuteResult.ERROR);
            result.setMsg(MsgConsts.COMPILE_ERROR + compileResult.get("error"));
            CodeRunResultMap.map.put(javaCode.getNumber(), result);
            return;
        }

        String className = JavaCodeUitls.getClassName(javaCode.getCode());
        try {
            Object ret = javaCodeCompiler.run(className, javaCode.getMethod());
            result.setResult(ExecuteResult.SUCCESS);
            result.setData(ret);
            CodeRunResultMap.map.put(javaCode.getNumber(), result);
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
            StringWriter stringWriter = new StringWriter();
            e.getCause().printStackTrace(new PrintWriter(stringWriter, true));
            String content = stringWriter.toString();
            String[] errors = content.split("\n");
            String errorInfo = errors[0] + errors[1];

            result.setResult(ExecuteResult.ERROR);
            result.setMsg(MsgConsts.RUNTIME_EXCEPTION + errorInfo);
            CodeRunResultMap.map.put(javaCode.getNumber(), result);
            return;
        }

    }
}

